#include "ReceptorDelta.h"

void ReceptorDelta::CalcularHashesVarios()
{
    StreamBloqueante SBloq(this->RutaFile,std::ios::in | std::ios::binary);
    std::fstream& ArDelRECEPTOR = SBloq.stream();
    unsigned int Chunks = ceil((this->FileSize) / float(TAM_PEDAZO) );
    //std::cout << "file size " << this->FileSize << std::endl;
    //std::cout << "div sin redondear "<< (this->FileSize) / float(TAM_PEDAZO) << std::endl;
    unsigned int NumeroDeChunk = 0;
    //std::cout << "Archivo del Receptor" << std::endl;

    //while( ArDelRECEPTOR.good() )
    while( ArDelRECEPTOR.good() )
    {
        char buffer[TAM_PEDAZO+1];
        ArDelRECEPTOR.read(buffer,TAM_PEDAZO);
        if ( ArDelRECEPTOR.gcount() == 0 ){break;}
        buffer[ArDelRECEPTOR.gcount()]='\0';
        std::string hexbuffer;
        BinToHex((uint8_t*)buffer,ArDelRECEPTOR.gcount(),hexbuffer);
        MD5 md5( hexbuffer );
        ADLER32 ad32( hexbuffer );
        std::string mdfive = md5.hexdigest();
        std::string adthirty2 = ad32.hexdigest();
        //std::cout << NumeroDeChunk << ")" << "size:"<< ArDelRECEPTOR.gcount() <<
        //            "|"<< buffer << "|"<< adthirty2 << "|" << mdfive <<std::endl;

        PaqueteHashReceptor PdH( NumeroDeChunk , mdfive , adthirty2 );
        this->ListaDeHashes.push_back(PdH);
        NumeroDeChunk += 1;
    }
    if ( this->ListaDeHashes.size() != Chunks )
    {
        std::cout << "Chunks " << Chunks << std::endl;
        std::cout << "NumeroDeChunk " << this->ListaDeHashes.size() << std::endl;
        throw MyException("ERROR MORTAL AL HASHEAR ARCHIVO DEL RECEPTOR ");
    }
}
    //devuelve todos los hashes calculados
std::list<PaqueteHashReceptor> ReceptorDelta::RecuperarHashes()
{
    return this->ListaDeHashes;
}

    //esto se puede optimizar usando DatosTrasmitidos
std::string ReceptorDelta::Serializar()
{
    std::string TotalSerializado;

    std::list<PaqueteHashReceptor>::iterator it = this->ListaDeHashes.begin();
    std::list<PaqueteHashReceptor>::iterator itEnd = this->ListaDeHashes.end();

    while( it != itEnd )
    {
        PaqueteHashReceptor PhR = *it;
        TotalSerializado.append( PhR.Serializar() );
        it++;
    }
    return TotalSerializado;
}

bool ReceptorDelta::UpdatearArchivoRespectoAemisor(DatosTrasmitidos<Diferencial> tot)
{
    std::cout << "updateando file" << std::endl;
    std::list<Diferencial> Ld = tot.getDatos() ;

    std::list<Diferencial>::iterator it = Ld.begin() ;
    std::list<Diferencial>::iterator itEnd = Ld.end() ;

    //levanto todo el archivo nuevo en memoria
    std::string ARCHIVO_NUEVO;
    LectorDeSegmento LectSeg( this->RutaFile );

    while ( it != itEnd )
    {
        Diferencial dif = *it;
        std::string delta ;
        delta = dif.getDelta() ;

        unsigned int NumBloque = dif.getNmatch() ;
        //std::cout << dif.Serializar() << std::endl;
        if ( NumBloque >= 0 )
        {
            //aca leo del archivo original
            std::string BloqueOri = LectSeg.getDif(NumBloque*TAM_PEDAZO,TAM_PEDAZO);

            std::string NuevaEntrada = delta + BloqueOri;

            ARCHIVO_NUEVO.append(NuevaEntrada);
        }
        else
        {   //el final del archivo
            ARCHIVO_NUEVO.append(delta);
        }

        it++;
    }
    //std::cout << ARCHIVO_NUEVO << std::endl;
    //voy a sobreescribir el archivo viejo del receptor
    StreamBloqueante SBloq(this->RutaFile,std::ios::out|std::ios::binary);
    std::fstream& ArDelRECEPTOR = SBloq.stream();

    int size =(ARCHIVO_NUEVO.size()/2);
    uint8_t * datos= new uint8_t[size];
    hexABin(ARCHIVO_NUEVO,datos);
    ArDelRECEPTOR.write((char*)datos,size);
    delete[] datos;
    return true;
}


